<!--
 * @Author: fengxx
 * @Date: 2025-09-05 09:19:27
 * @LastEditors: fengxx
 * @LastEditTime: 2025-10-23 10:56:11
-->
<script setup lang="ts">
import {
  ref,
  type Ref,
  shallowRef,
  reactive,
  shallowReactive,
  computed,
  type Reactive,
  useTemplateRef,
  watch,
  onMounted,
  watchEffect,
  onWatcherCleanup,
  type ComputedGetter,
  onBeforeMount,
  provide,
  readonly,
  onUnmounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
} from 'vue'
import axios from 'axios'
import TheWelcome from '@/components/TheWelcome.vue'
import HelloWorld from '@/components/HelloWorld.vue'
import ListItem from '@/components/ListItem.vue'
import ChildTest from '@/components/ChildTest.vue'
import { useCounterStore } from '@/stores/counter'
import { useProductStore } from '@/stores/product'
import { storeToRefs } from 'pinia'
import { useRoute, useRouter } from 'vue-router'

// const props = defineProps<{
//   query: string
//   age: number
//   // newsletterPopup: boolean
//   // id: string
// }>()
// const buttonName: Ref<string> = ref('我的按钮')
// const span: string = `<span style="color: red"><span>${buttonName.value}</span></span>`
// const id: string = 'myId' // 当变量的名称和属性名称相同时可以通过 :变量名 简写
// const show: boolean = true
// const objectOfAttrs = {
//   id: 'container',
//   class: 'wrapper',
//   style: 'background-color:write',
// }
// const type: string = 'C'

// const items = [
//   {
//     id: 1,
//     text: '标题1',
//     src: 'https://gips1.baidu.com/it/u=1647344915,1746921568&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280',
//   },
//   {
//     id: 2,
//     text: '标题2',
//     src: 'https://gips1.baidu.com/it/u=1647344915,1746921568&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280',
//   },
//   {
//     id: 1,
//     text: '标题3',
//     src: 'https://gips1.baidu.com/it/u=1647344915,1746921568&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280',
//   },
//   {
//     id: 1,
//     text: '标题4',
//     src: 'https://gips1.baidu.com/it/u=1647344915,1746921568&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280',
//   },
// ]

// const attributeName = 'href'
// const url = 'http://www.baidu.com'

// const fun = function () {
//   console.log('dsfdsg')
//   buttonName.value = buttonName.value + '1'
//   // return 1
// }

// const eventName: string = 'click'

// const a: Ref<string> = ref('kkk') // .value

// ref: 具有深层响应性（对象不管嵌套多深，改变里面属性的值都会及时更新到页面上）
const obj1 = ref({
  a: {
    c: '1',
  },
  b: true,
})
// shallowRef：浅层响应性（只对value一层具有响应性，当对象层级很深时，改变深层对象属性的值不会更新到页面上）
// const obj1 = shallowRef({
//   a: {
//     c: '1',
//   },
// })

// reactive: 参数只能是对象，当前的对象就具有响应性
// reactive：如果对reactive对象值直接重新赋值，就不在具有响应性
// let obj2 = reactive({
//   a: '1',
// })

// const obj3 = shallowReactive({
//   a: {
//     c: '1',
//   },
// })
// const obj = ref({
//   first: 'zhan',
//   last: 'junxi',
// })
const arr = reactive([1, 2, 3])
// const pEle = useTemplateRef('p-ele')
// const listData = ref([])

// const changeA = () => {
//   a.value += '1'
//   obj.value.a.c = '8888'
//   arr.value.push(arr.value.length + 1)
// }

// const changeAA = () => {
//   obj1.value = {
//     a: {
//       c: '8888',
//     },
//   }
//   // obj1.value.a.c = '8888'
// }

// const changeAAA = () => {
//   // reactive数据直接挂载在对象上，所以对其修改不需要通过.value
//   obj2.a = '8888'
//   obj2 = {
//     a: 'aa2',
//   }
// }

// const changeAAAA = () => {
//   let { a } = obj3
//   a = {
//     c: '8888',
//   }
//   console.log(a, obj3.a)
//   // obj3.a = {
//   //   c: '8888',
//   // }
//   // obj3.a.c = '8888'
// }

// const object = { id: ref(1) }
// const { id } = object

// const full = computed(() => `${obj.value.first} ${obj.value.last}`)

// 计算属性（默认只读）
// const arrLen = computed((previous) => {
//   // 计算属性的上一次结果
//   // console.log(previous)
//   return arr.length
// })

// 计算属性支持getter和setter
// const arrLen = computed({
//   get(previous) {
//     console.log(previous)
//     return arr.length
//   },
//   set(value: number) {
//     arr.push(value)
//   },
// })

// const changeArr = () => {
//   arr.push(1)
//   // console.log(arrLen.value) // 3
//   // arrLen.value = 1
//   // console.log(arrLen.value) // 4
// }

// const isActive = ref(true)
// const hasError = ref(true)
// const classObj = reactive({
//   active: isActive,
//   'text-danger': hasError,
// })
interface A {
  type?: string
}

const activeColor = ref('red')
const fontSize = ref('30px')
const current = ref(1)
const isActive = ref(true)
const error: Ref<A | null> = ref(null)
const activeClass = ref('active')
const errorClass = ref('text-danger')
const classObject = computed(() => ({
  active: isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal',
}))
const baseStyles = ref({
  fontSize: '16px',
})
const overridingStyles = reactive({
  color: 'blue',
})

const setCurrent = (c: number) => {
  current.value = c
}

const showEle: Ref<boolean> = ref(true)

interface Item {
  id: number
  message: string
  children?: Item[]
}

const items: Reactive<Item[]> = reactive([
  {
    id: 1,
    message: '分组1',
    children: [
      {
        id: 1.1,
        message: '成员1',
        children: [],
      },
      {
        id: 1.2,
        message: '成员2',
        children: [],
      },
      {
        id: 1.3,
        message: '成员3',
        children: [],
      },
    ],
  },
  {
    id: 2,
    message: '分组2',
    children: [
      {
        id: 2.1,
        message: '成员1',
        children: [],
      },
      {
        id: 2.2,
        message: '成员2',
        children: [],
      },
      {
        id: 2.3,
        message: '成员3',
        children: [],
      },
    ],
  },
])

const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10',
})

// function say(message: string, e: Event) {
//   // console.log(e)
//   // alert(message)
// }

// const text = ref(true)
const checkedNames = ref(['Jack1']) // 多选框
const radioChecked = ref('Jack1') // 单选框
const selected = ref(['Jack', 'Jack1'])
const checkItems = [
  {
    value: 'Jack',
    label: 'Jack',
  },
  {
    value: 'Jack1',
    label: 'Jack1',
  },
  {
    value: 'Jack2',
    label: 'Jack2',
  },
  {
    value: 'Jack3',
    label: 'Jack3',
  },
]
const toggle = ref('yes')

// const computedRes = computed((previous)=>{
//   console.log(previous)
//   return toggle.value.length
// })

const question = ref('1')
const answer = ref('Questions usually contain a question mark. ;-)')
const loading = ref(false)
// 可以直接侦听⼀个 ref
// watch(question, async (newQuestion, oldQuestion) => {
//   console.log(oldQuestion, newQuestion)
//   if (newQuestion.includes('?')) {
//     loading.value = true
//     answer.value = 'Thinking...'
//     try {
//       const res = await fetch('https://yesno.wtf/api')
//       answer.value = (await res.json()).answer
//     } catch (error) {
//       answer.value = 'Error! Could not reach the API. ' + error
//     } finally {
//       loading.value = false
//     }
//   }
// })

// const obj = reactive({ count: 0 })
// const state = reactive({ obj: { count: 0 } })

// watch(
//   // 观察对象属性时，应该用函数返回值的形式(返回该属性的 getter 函数)
//   // function () {
//   //   return obj.count
//   // },
//   // ()=>obj.count,
//   // (count) => {
//   //   console.log(`Count is: ${count}`)
//   // },
//   // watch可以观察到对象的一层变化，当对象属性值被更改时，只要不是整体替换，新旧值是相等的
//   // 当对象层级超过一级时，属性改变观察不到，整体替换可以观察到变化
//   // obj,
//   // (newObj, oldObj) => {
//   //   console.log(newObj, oldObj)
//   // },
//   () => state.obj,
//   (newObj, oldObj) => {
//     // console.log(newObj, oldObj)
//   },
//   // deep: 深层观察引用类型； immediate: 立即调用watch; once: watch的回调只执行一次
//   { deep: 1, immediate: true, once: true },
// )

// 第一个参数： ref/reactive/arr/函数返回值
// 第二个参数：回调函数，用来处理watch的值变化要做什么
// 第三个参数：对象，用来规范watch的执行
// watch(toggle, () => {}, {})

// const result = computed(()=>{
//   return toggle
// })

// watch=>watchEffect
// watch(
//   question,
//   async () => {
//     const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${question.value}`)
//     // console.log(response)
//   },
//   { immediate: true },
// )
// // // watch的简写
// const unwatch = watchEffect(async () => {
//   const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${question.value}`)
//   // console.log(response)
//   //  data.value = await response.json()
// })

watch(
  question,
  (newId, oldId, onCleanup) => {
    const controller = new AbortController()
    fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
      // 回调逻辑
    })

    // console.log(pEle.value?.value)
    // console.log(document.getElementById('pp').value, newId)
    onCleanup(() => {
      // 清理逻辑
      controller.abort()
    })
    // 当侦听过程中接口请求没有结束，该函数会强行终止
    // onWatcherCleanup(() => {
    //   console.log('000')
    //   // 终⽌过期请求
    //   controller.abort()
    // })
  },
  { flush: 'sync' },
)

const myInput = useTemplateRef('my-input')
// const theWelcome = useTemplateRef('the-welcome')
const checkboxs = useTemplateRef('checkboxs')
// const myRef = ref(null)
// const setRef = (el) => {
//   myRef.value = el
// }

// function changeObj() {
//   obj1.value = {
//     a: {
//       c: '2',
//     },
//     b: true,
//   }
//   // obj1.value.a.c = '2'
//   obj.count++
//   state.obj.count++
//   // state.obj = {
//   //   count: 3,
//   // }
//   // console.log(theWelcome.value?.rr)
// }

const b: Ref<number> = ref(0)
const a = computed((p: number | undefined) => {
  const c: number = p || 0
  // console.log(b.value, c)
  return c + b.value
})

const c: Ref<number> = ref(0)
watch(b, (n, o) => {
  // console.log(n, o)
  c.value = n + o
})

const count11 = ref(0)
const changeCount = () => {
  count11.value = 1
}

// 提供者（第一个参数：提供内容的名称， 第二个参数：提供内容的值）
provide('rootMsg', {
  count11: readonly(count11),
  changeCount,
})

provide('key', count11)

function fun() {
  b.value++
  // console.log(a.value)
  couterStore.$reset()
}
// reactive类型
const couterStore = useCounterStore()
const productStore = useProductStore()
// couterStore.count = 4
const { count, num, newCount, classfys } = storeToRefs(couterStore)

// console.log(couterStore.count, productStore.name)

// 订阅当前store的state信息（第一个参数：操作对象， 第二个参数：state）
couterStore.$subscribe(
  (mutation, state) => {
    //   mutation.type // 'direct' | 'patch object' | 'patch function'
    //  // 和 cartStore.$id ⼀样
    //  mutation.storeId // 'cart'
    //  // 只有 mutation.type === 'patch object'的情况下才可⽤
    //  mutation.payload // 传递给 cartStore.$patch() 的补丁对象。

    console.log(mutation.type, mutation.storeId, state.count)
  },
  // { detached: true },
)

// const unsubscribe = couterStore.$onAction(
//   ({
//     name, // action 名称
//     store, // store 实例，类似 `someStore`
//     args, // 传递给 action 的参数数组
//     after, // 在 action 返回或解决后的钩⼦
//     onError, // action 抛出或拒绝的钩⼦
//   }) => {
//     // 为这个特定的 action 调⽤提供⼀个共享变量
//     const startTime = Date.now()
//     // 这将在执⾏ "store "的 action 之前触发。
//     console.log(`Start "${name}" with params [${args.join(', ')}].`)
//     // 这将在 action 成功并完全运⾏后触发。
//     // 它等待着任何返回的 promise
//     after((result) => {
//       console.log(`Finished "${name}" after ${Date.now() - startTime}ms.\nResult: ${result}.`)
//     })
//     // 如果 action 抛出或返回⼀个拒绝的 promise，这将触发
//     onError((error) => {
//       console.warn(`Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`)
//     })
//   },
//   true,
// )
// ⼿动删除监听器
// unsubscribe()

const changeStore = () => {
  // couterStore.getCount()
  // count.value = 1
  // couterStore.increment()
  // couterStore.$patch({
  //   count: 4,
  //   num: 8,
  // })
  couterStore.$patch((state) => {
    state.count = 4
  })

  // 整体替换，推荐用$patch
  // couterStore.$state = {
  //   count: 4,
  //   num: 2,
  // }
  productStore.$patch((state) => {
    state.userList.push({
      name: '小明',
      age: 18,
    })
  })
}
// const intervalId: number = 0

// dom挂载之前的钩子
// onBeforeMount(() => {
//   console.log('beforeMounted')
// })

// dom挂载之后的钩子
onMounted(() => {
  couterStore.increment()
  // intervalId = setInterval(() => {
  //   console.log('dhgfj')
  // }, 1000)

  // console.log('mounted')
  // couterStore.getCount()

  // console.log(myInput.value?.value)
  // console.log(myInput.value, document.getElementById('my-input'))
  myInput.value?.focus()
  // console.log(myInput.value?.value)
  // console.log(theWelcome.value?.rr)
  // theWelcome.value?.fun()
  // console.log(checkboxs.value)
  // console.log(myRef.value?.value)
  // checkboxs.value?.forEach((item) => {
  //   // console.log(item)
  // })

  // axios
  //   .get('http://localhost:3000/users')
  //   .then(function (response) {
  //     listData.value = response.data
  //     // console.log(response.data)
  //   })
  //   .catch(function (error) {
  //     console.log(error)
  //   })
  // fetch('https://yesno.wtf/api').then(()=>{
  // })
})

// // 组件更新之前
// onBeforeUpdate(() => {
//   console.log('beforeUpdate')
//   console.log(classfys.value)
// })

// // 组件更新之后
// onUpdated(() => {
//   console.log('updated')
//   console.log(classfys.value)
// })

// // 组件卸载之前
// onBeforeUnmount(() => {
//   console.log('beforemount')
// })
// // 组件卸载之后
// onUnmounted(() => {
//   console.log('unmounted')
//   clearInterval(intervalId)
//   intervalId = 0
// })

// // 项目的路由实例
// const router = useRouter()
// // 当前页面的路由实例
// const route = useRoute()

// console.log(router, route)

// const onBeforeEnter = (el, done) => {
//   el.style.color = 'red'
//   el.style.transition = 'color 0.5s'
//   console.log('beforeEnter')
// }
// const onEnter = (el, done) => {
//   el.style.color = 'blue'

//   console.log('enter')
//   done()
// }
// const onAfterEnter = () => {
//   console.log('afterEnter')
// }
// const onBeforeLeave = (el) => {
//   el.style.color = 'green'
//   console.log('beforeLeave')
// }
// const onLeave = (el) => {
//   el.style.color = 'red'
//   console.log('leave')
// }
// const onAfterLeave = () => {
//   console.log('afterLeave')
// }

const show = ref(true)
// const items1: Reactive<number[]> = reactive([1, 2, 3])

type ComponentKey = 'ChildTest' | 'HelloWorld'
const components = {
  ChildTest,
  HelloWorld,
} as const

const currentComponent = ref<ComponentKey>('ChildTest')

watch(show, () => {
  currentComponent.value = show.value ? 'ChildTest' : 'HelloWorld'
})

// 在任意位置插入一个元素
// const onAddItem = () => {
//   const curLen = items1.length
//   const insertIdx = Math.floor(Math.random() * curLen)
//   // splice，参数1：从当前下标开始删除；参数2：删除多少个；参数3：删除之后插入的具体元素
//   items1.splice(insertIdx, 0, insertIdx)
// }
// // 在任意位置删除一个元素
// const onDelItem = () => {
//   const curLen = items1.length
//   const insertIdx = Math.floor(Math.random() * curLen)
//   items1.splice(insertIdx, 1)
// }
const open = ref(false)
const isMobile = ref(false)
</script>

<template>
  <div id="lili">lili</div>
  <div>
    <button @click="open = true">Open Modal</button>
  </div>
  <!-- disabled: 禁用teleport目标的传输 -->
  <!-- defer: 推迟 Teleport 的⽬标解析，直到应⽤的其他部分挂载 -->
  <Teleport to="#lili" defer :disabled="isMobile">
    <div v-if="open && !isMobile" class="modal">
      <div>
        <p>Hello from the modal!</p>
        <button @click="open = false">Close</button>
      </div>
    </div>
  </Teleport>
  <Teleport to="body">
    <div>B</div>
  </Teleport>

  <!-- <div>
    <button @click="onAddItem">添加</button>
    <button @click="onDelItem">删除</button>
  </div>
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items1" :key="item">
      {{ item }}
    </li>
  </TransitionGroup>
  <ChildTest v-if="show" />
  <TheWelcome v-else /> -->
  <!-- 动态组件 -->
  <!-- <component :is="show ? ChildTest : TheWelcome"></component> -->
  <!-- <transition mode="out-in">
    <component :is="components[currentComponent]" msg="fdsgd" :key="currentComponent"></component>
  </transition> -->
  <!-- include: 包含哪些缓存；exclude：不包含哪些缓存 -->
  <!-- max： 设置最大缓存组件数，该值大于0 -->
  <!-- <keep-alive :include="['ChildTest']" exclude="HelloWorld" :max="0"> -->
  <keep-alive>
    <component :is="components[currentComponent]" :key="currentComponent"></component>
  </keep-alive>

  <button @click="show = !show">Toggle</button>
  <!-- <transition
    @before-enter="onBeforeEnter"
    @enter="onEnter"
    @after-enter="onAfterEnter"
    @before-leave="onBeforeLeave"
    @leave="onLeave"
    @after-leave="onAfterLeave"
    :css="false"
  >
    <div v-if="show">hh</div>
  </transition> -->
  <!-- <Transition name="bounce" enter-from-class="hh" :duration="{ enter: 500, leave: 800 }">
    <div v-if="show" style="text-align: center">
      <p>hello</p>
      <p>sdfdsgf</p>
    </div>
  </Transition> -->
  <!-- <Transition>
    <div v-if="show">
      <p>hello</p>
      <p>sdfdsgf</p>
    </div>
  </Transition> -->

  <!-- <p class="pp" :style="{ opacity: show ? 1 : 0 }">hello</p> -->

  <!-- <router-link to="/userList">跳转</router-link> -->
  <!-- <div @click="changeStore">{{ count11 }}{{ couterStore.count }}</div> -->
  <div style="color: blueviolet; font-size: 22px">
    <!-- {{ props.age }} -->
    <!-- {{ props.newsletterPopup ? '弹出新闻' : '隐藏新闻' }} -->
    <!-- {{ props.query }} -->
  </div>
  <div v-for="(value, index) in classfys.met" :key="index">
    <div>{{ `${value}${classfys.names[index]}${classfys.price[index]}` }}</div>
  </div>

  <div @click="changeStore">
    {{ count11 }}{{ count }}{{ num }}{{ newCount }}{{ productStore.currentUser('小明')
    }}{{ couterStore.otherCount(1) }}ttyyggyyy{{ productStore.count }}
  </div>
  <div v-for="(value, index) in productStore.userList" :key="index">
    <span>姓名： {{ value.name }}</span>
    <span>年龄：{{ value.age }}</span>
  </div>
  <p @click="fun">
    {{ obj1.a.c }}{{ c }}{{ a }}
    Ask a yes/no question:
    <input v-model="question" :disabled="loading" ref="p-ele" id="pp" />
  </p>
  <p>{{ answer }}</p>

  <!-- <el-table :data="listData" style="width: 100%">
    <el-table-column prop="id" label="id" width="180" />
    <el-table-column prop="name" label="Name" width="180" />
    <el-table-column prop="password" label="Address" />
  </el-table> -->

  <!-- .lazy 代表onchange事件后更新value -->
  <input v-model.lazy="toggle" ref="my-input" id="my-input" />
  <!-- <input v-model.trim="toggle" :ref="(el) => setRef(el)" /> -->

  <div>Checked names: {{ checkedNames + toggle }}</div>
  <span v-for="value in checkItems" :key="value.value" ref="checkboxs">
    <input type="checkbox" :id="value.value" :value="value.value" v-model="checkedNames" />
    <label :for="value.value">{{ value.label }}</label>
  </span>
  <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />

  <div>Checked name: {{ radioChecked }}</div>
  <span v-for="value in checkItems" :key="value.value">
    <input type="radio" :id="value.value" :value="value.value" v-model="radioChecked" />
    <label :for="value.value">{{ value.label }}</label>
  </span>

  <div>Selected: {{ selected }}</div>
  <select v-model="selected" multiple>
    <option disabled value="">请选择</option>
    <option v-for="(item, index) in checkItems" :key="index" :value="item.value">
      {{ item.label }}
    </option>
  </select>

  <!-- .self: 父元素点击禁止向下穿透；stop: 子元素点击禁止向上穿透 -->
  <!-- <form @submit.prevent="formSubmit" ref="my-form">
    <input
      type="checkbox"
      v-model="text"
      :true-value="'dynamicTrueValue'"
      :false-value="'dynamicFalseValue'"
      @keyup.page-down="
        () => {
          console.log(text)
        }
      "
    />
    <button type="submit">Say bye</button>
  </form> -->

  <!-- <button @click="(event) => say('bye', event)">Say bye</button> -->
  <ul v-on:click="arr.push(4)">
    <!-- 当循环体是对象时，第二个参数是对象的key, 第三个参数是索引 -->
    <li v-for="(value, key, index) in myObject" :key="key">
      {{ `${index} ${key}: ${value}` }}
    </li>
  </ul>
  <template v-for="n in 10" :key="n">
    <span>{{ n }}</span>
  </template>

  <li v-for="item in items" :key="item.id">
    <div>{{ item.message }}</div>
    <div>
      <ListItem v-for="childItem in item.children" :key="childItem.id" :list-item="childItem" />
      <!-- <span v-for="childItem in item.children" :key="childItem.id"> {{ childItem.message }} </span> -->
    </div>
  </li>
  <template v-if="showEle">
    <h1 v-show="false">Title</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
  </template>
  <template v-else>
    <div>else</div>
  </template>
  <main>
    <div v-html="'<span>1</span>'"></div>
    <div :style="{ color: activeColor, fontSize: fontSize, fontWeight: 700 }">内联样式</div>
    <div :style="[baseStyles, overridingStyles]">内联样式1</div>
    <!-- <div class="static" :class="{ active: isActive, 'text-danger': hasError }">我是傻瓜</div> -->
    <div class="static" :class="classObject">我是傻瓜</div>
    <div :class="[isActive ? 'static' : '', activeClass, errorClass]"></div>
    <div :class="[{ [activeClass]: isActive }, errorClass]"></div>
    <template v-if="showEle">
      <div
        v-for="(value, index) in arr"
        :style="{ color: current == value ? 'red' : '#333' }"
        :class="{ active: current == value }"
        @click="setCurrent(value)"
        :key="index"
      >
        {{ value }}
      </div>
      <!-- <div v-for="(value,index) in source" :key="index"></div> -->
    </template>

    <!-- <div>{{ full }}</div>
    <div @click="changeArr">{{ arrLen }}</div> -->
    <!-- <div v-show="false">{{ a }}{{ id + '000' }}</div>
    <div @click="changeA">{{ obj.a.c }}</div>
    <div @click="changeAA">{{ obj1.a.c }}</div>
    <div @click="changeAAA">{{ obj2.a }}</div>
    <div @click="changeAAAA">{{ obj3.a.c }}</div>
    <div v-for="value in arr" :key="value">{{ value }}</div> -->
    <HelloWorld v-for="(value, idx) in arr" :key="idx" :msg="`${value}`" />
    <TheWelcome ref="the-welcome" class="pppp" />
    <!-- <TheWelcome></TheWelcome>
    <the-welcome></the-welcome> -->
  </main>
</template>
<style scoped>
.modal {
  position: fixed;
  z-index: 999;
  top: 20%;
  left: 50%;
  width: 300px;
  margin-left: -150px;
}
/* .bounce-enter-active {
  animation: bounce-in 0.5s;
}
.bounce-leave-active {
  animation: bounce-in 0.5s reverse;
} */
/* @keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
} */
/* fade和name一致 */
/* .bounce-enter-active,
.bounce-leave-active {
  transition: opacity 0.5s ease;
} */
/* .bounce-enter-from, */
/* .hh,
.bounce-leave-to {
  opacity: 0;
} */

.list-move,
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
/* 确保将离开的元素从布局流中删除
 以便能够正确地计算移动的动画。 */
.list-leave-active {
  position: absolute;
}

/* .v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
  opacity: 0;
} */
/* 默认样式可以不写 */
/* .v-enter-to,
.v-leave-from {
  opacity: 1;
} */

/* .pp {
  transition: opacity 0.5s ease;
}*/

.static {
  border: 1px solid red;
}
.active {
  color: red;
}
.text-danger {
  font-weight: 700;
}
</style>
